import io

from aiogram import Bot, Dispatcher, F
from aiogram.filters import Text
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import any_state
from aiogram.types import Message, ReplyKeyboardRemove
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import sessionmaker

from app.bot.keyboards.reply import user_keyboard
from app.bot.states.states import AddTask
from app.bot.utils.logger import log
from app.bot.utils.scheduler import jobs
from app.database.functions.stats import update_stats, update_user_stats
from app.database.functions.tasks import add_task


async def add_new_task(message: Message, state: FSMContext) -> None:
    """
    Добавление задания на лайки
    """

    if "лайки" in message.text:
        await state.update_data(task_type="likes")
        await message.answer(
            "Отправьте мне ссылку на фанпейдж или на пост",
            reply_markup=ReplyKeyboardRemove(),
        )
    elif "комментарии" in message.text:
        await state.update_data(task_type="comments")
        await message.answer(
            "Отправьте мне ссылку на пост", reply_markup=ReplyKeyboardRemove()
        )
    await message.answer("Отправьте /cancel, чтобы вернуться в главное меню")
    await state.set_state(AddTask.waiting_link)


async def select_link(message: Message, state: FSMContext) -> None:
    if "facebook.com" in message.text:
        await state.update_data(link=message.text)
        data = await state.get_data()
        if data.get("task_type") == "likes":
            await message.answer("Введите желаемое количество лайков")
        elif data.get("task_type") == "comments":
            await message.answer("Введите желаемое количество комментариев")
        await state.set_state(AddTask.waiting_amount)
    else:
        await message.answer("Вы ввели некорректную ссылку")
        await state.set_state(AddTask.waiting_link)
        return


async def select_amount(message: Message, state: FSMContext) -> None:
    if message.text.isdigit():
        await state.update_data(count=int(message.text))
        data = await state.get_data()
        if data.get("task_type") == "likes":
            await message.answer("Введите интервал между лайками в минутах")
            await state.set_state(AddTask.waiting_interval)
        elif data.get("task_type") == "comments":
            await message.answer(
                "Отправьте файл или текст с комментариями (каждый комментарий с новой строки)"
            )
            await state.set_state(AddTask.waiting_file)
        else:
            await message.answer("Введите количество цифрой")
            await state.set_state(AddTask.waiting_amount)
            return


async def select_file_with_comments(
    message: Message, bot: Bot, state: FSMContext
) -> None:

    comment_file_text = None

    if message.document:
        if ".txt" not in message.document.file_name:
            await message.answer("Вы отправили не txt файл")
            await state.set_state(AddTask.waiting_file)
            return
        else:
            file = io.BytesIO()
            file.seek(0)
            await bot.download(message.document, destination=file)
            comment_file_text = "\n".join([line.decode() for line in file.readlines()])
    elif message.text:
        comment_file_text = "\n".join(message.text.split("\n"))
        await state.update_data(comment_file_text=comment_file_text)

    await state.update_data(comment_file_text=comment_file_text)
    await message.answer("Введите интервал между комментариями в минутах")
    await state.set_state(AddTask.waiting_interval)


async def select_interval(
    message: Message,
    bot: Bot,
    session: AsyncSession,
    session_factory: sessionmaker,
    scheduler: AsyncIOScheduler,
    state: FSMContext,
) -> None:
    if message.text.isdigit():
        await state.update_data(interval=int(message.text))
        await message.answer(
            "Ваша задача принята в работу", reply_markup=user_keyboard()
        )
    else:
        await message.answer("Введите интервал цифрой")
        await state.set_state(AddTask.waiting_amount)
        return
    data = await state.get_data()
    if data.get("comment_file_text"):
        await add_task(
            session,
            data.get("task_type"),
            message.from_user.id,
            data.get("link"),
            data.get("count"),
            data.get("interval"),
            data.get("comment_file_text"),
        )
    else:
        await add_task(
            session,
            data.get("task_type"),
            message.from_user.id,
            data.get("link"),
            data.get("count"),
            data.get("interval"),
        )
    await state.clear()
    scheduler.add_job(
        jobs.check_tasks,
        "interval",
        name="Likes/comments",
        minutes=2,
        args=(bot, session_factory, scheduler, message.from_user.id),
    )
    if data.get("task_type") == "likes":
        await update_stats(
            session,
            likes=data.get("count"),
        )
        await update_user_stats(
            session,
            message.from_user.id,
            likes=data.get("count"),
        )
    elif data.get("task_type") == "comments":
        await update_stats(
            session,
            comments=data.get("count"),
        )
        await update_user_stats(
            session,
            message.from_user.id,
            comments=data.get("count"),
        )
    log.info(
        f"Добавлена задача {data.get('task_type')} для пользователя {message.from_user.id}"
    )


def register_tasks_handlers(dp: Dispatcher):
    dp.message.register(
        add_new_task, Text(text="👍 Накрутить лайки", ignore_case=True), any_state
    )
    dp.message.register(
        add_new_task, Text(text="💬 Накрутить комментарии", ignore_case=True), any_state
    )
    dp.message.register(select_link, AddTask.waiting_link)
    dp.message.register(select_amount, AddTask.waiting_amount)
    dp.message.register(
        select_file_with_comments,
        AddTask.waiting_file,
        F.content_type.in_(["text", "document"]),
    )
    dp.message.register(select_interval, AddTask.waiting_interval)
